<template>
  <div class="form-number">
    <input 
      autocomplete="off"
      ref="input" 
      :type="type" 
      :id="`form_${field.fieldName}`"
      :maxlength="inputMaxLength"
      :max="maxNumber"
      :min="minNumber"
      :placeholder="placeholder" 
      :value="value"
      @input="input"
    >
  </div>
</template>

<script>

import FormMixin from '@src/component/form/mixin/form';
import { FORM_FIELD_TEXT_MAX_LENGTH } from '@src/model/const/Number.ts';
import { isNumber, isNull, isString } from '@src/util/type'

export default {
  name: 'number-search',
  mixins: [FormMixin],
  props: {
    value: [String, Number],
    max: {
      type: Number,
    },
    min: {
      type: Number,
    },
    maxLength: {
      type: Number
    },
    type: {
      type: String,
      default: 'number'
    },
    validator: {
      type: Function,
    }
  },
  computed: {
    getInput() {
      return this.$refs.input || this.$refs.textarea;
    },
    inputMaxLength() {
      return this.maxLength || FORM_FIELD_TEXT_MAX_LENGTH
    },
    maxNumber() {
      return isNumber(this.max) ? this.max : null
    },
    minNumber() {
      return isNumber(this.min) ? this.min : null
    },
    nativeInputValue() {
      return this.value === null || this.value === undefined ? '' : String(this.value);
    },
  },
  watch: {
    // native input value is set explicitly
    // do not use v-model / :value in template
    nativeInputValue() {
      this.setNativeInputValue();
    },
  },
  mounted() {
    const InputEl = this.$refs.input;
    
    InputEl.addEventListener('paste', this.pasteEventHandler)
  },
  beforeDestroy() {
    this.$refs.input.removeEventListener('paste', this.pasteEventHandler);
  },
  methods: {
    input(event){
      let oldValue = null;
      let newValue = event.target.value;
      
      if(newValue == this.nativeInputValue) return;
      
      if (newValue === '') {
        this.$nextTick(() => {
          event.target.value = '';
        });
      }
      
      const isStringEmpty = isString(newValue) && newValue === ''
      
      if (isNumber(this.max) && newValue > this.max && !isStringEmpty) {
        newValue = this.max
      } 
      else if (isNumber(this.min) && newValue < this.min && !isStringEmpty) {
        newValue = this.min
      }
      
      if (this.validator) {
        newValue = this.validator(newValue)
        event.target.value = newValue
      }
      
      this.$emit('update', {newValue, oldValue, field: this.field});
      this.$emit('input', newValue);
    },
    setNativeInputValue() {
      const input = this.getInput;
      
      if (!input) return;
      if (input.value === this.nativeInputValue) return;
      
      input.value = this.nativeInputValue;
    },
    pasteEventHandler(event) {
      try {
        let number = event.clipboardData.getData('text')
        let newValue = number
        
        if (number.length > FORM_FIELD_TEXT_MAX_LENGTH) {
          newValue = number.slice(0, FORM_FIELD_TEXT_MAX_LENGTH)
        }
        
        if (!isNull(this.maxNumber) && this.maxNumber < newValue) {
          newValue = this.maxNumber
        }
        
        if (!isNull(this.minNumber) && this.minNumber > newValue) {
          newValue = this.minNumber
        }
        
        if (this.validator) {
          newValue = this.validator(newValue)
        }
        
        this.$emit('update', { newValue, field: this.field });
        this.$emit('input', newValue);
        
        event.preventDefault(); // 阻止粘贴默认事件造成，复制2次的问题
      } catch (error) {
        console.warn('form-number: paste -> error', error)
      }
    }
  }
}
</script>

<style lang="scss">
.form-number{
  width: 100%;
  input{
    width: 100%;
  }
}
</style>